package com.hxl.tech.gateway.auth.service;


import com.hxl.tech.gateway.auth.context.ContextHolder;
import com.hxl.tech.gateway.auth.dao.UserDao;
import com.hxl.tech.gateway.auth.dto.Page;
import com.hxl.tech.gateway.auth.dto.UserInfo;
import com.hxl.tech.gateway.auth.dto.user.UserFindDTO;
import com.hxl.tech.gateway.auth.dto.user.UserStateUpdateDTO;
import com.hxl.tech.gateway.auth.dto.user.req.ApplicationOauthLoginReqDTO;
import com.hxl.tech.gateway.auth.exception.AuthException;
import com.hxl.tech.gateway.auth.model.User;
import com.hxl.tech.gateway.auth.oauth.OAuthUser;
import com.hxl.tech.gateway.auth.util.AutoGenerateIDUtil;
import com.hxl.tech.gateway.auth.util.CopyUtil;
import com.hxl.tech.gateway.common.constant.AppConstant;
import com.hxl.tech.gateway.common.constant.Result;
import lombok.RequiredArgsConstructor;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * 用户 Service 
 * @author soliddq
 * @date 2023-10-10
 */
@Service
@RequiredArgsConstructor
@Transactional
public class UserService {

    private final UserDao userDao;
    private final EntityManager entityManager;

    public Page<User> page(UserFindDTO findDTO) {

        List<User> list = userDao.find(findDTO, true);
        Long total = userDao.count(findDTO);
        return Page.of(findDTO, total, list);
    }

    public User saveRegister(User user) {

        user.setUserId(AutoGenerateIDUtil.next(AppConstant.PREFIX_USER));
        this.checkUser(user.getUserId(), user.getPhone());
        user.setState(AppConstant.StateEnum.ENABLE);
        user.setRoleName(AppConstant.ROLE_DEVELOPER);
        user.setPassword(DigestUtils.md5Hex(user.getUserId() + user.getPassword()));
        user.setCreateBy(user.getRealName());
        user.setUpdateBy(user.getRealName());
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(user.getCreateTime());
        entityManager.persist(user);
        return user;
    }

    public User read(String userId) {

        UserInfo userInfo = ContextHolder.getUserInfo();
        if (!userInfo.getIsAdmin()) {
            userId = userInfo.getUserId();
        }
        return userDao.read(userId);
    }

    public User readByPhone(String phone) {

        return userDao.readByPhone(phone);
    }

    public User save(User user) {

        UserInfo userInfo = ContextHolder.getUserInfo();
        user.setUserId(AutoGenerateIDUtil.next(AppConstant.PREFIX_USER));
        this.checkUser(user.getUserId(), user.getPhone());
        user.setState(AppConstant.StateEnum.ENABLE);
        user.setPassword(DigestUtils.md5Hex(user.getUserId() + user.getPassword()));
        user.setCreateBy(userInfo.getRealName());
        user.setUpdateBy(userInfo.getRealName());
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(user.getCreateTime());
        entityManager.persist(user);
        return user;
    }

    public User update(User user) {

        User origUser = this.read(user.getUserId());
        if (Objects.isNull(origUser)) {
            throw new AuthException(Result.E10007);
        }

        UserInfo userInfo = ContextHolder.getUserInfo();
        if (StringUtils.isNotEmpty(user.getPhone())) {
            this.checkUser(origUser.getUserId(), user.getPhone());
            origUser.setPhone(user.getPhone());
        }
        if (StringUtils.isNotEmpty(user.getUserName())) {
            origUser.setUserName(user.getUserName());
        }
        if (StringUtils.isNotEmpty(user.getRealName())) {
            origUser.setRealName(user.getRealName());
        }
        if (StringUtils.isNotEmpty(user.getPassword())) {
            origUser.setPassword(DigestUtils.md5Hex(user.getUserId() + user.getPassword()));
        }
        if (userInfo.getIsAdmin()) {
            if (StringUtils.isNotEmpty(user.getRoleName())) {
                origUser.setRoleName(user.getRoleName());
            }
        }
        origUser.setUpdateBy(userInfo.getRealName());
        origUser.setUpdateTime(LocalDateTime.now());
        entityManager.merge(origUser);
        return origUser;
    }

    public User updateState(UserStateUpdateDTO stateUpdateDTO) {

        User origUser = this.read(stateUpdateDTO.getUserId());
        if (Objects.isNull(origUser)) {
            throw new AuthException(Result.E10007);
        }

        origUser.setState(stateUpdateDTO.getState());
        entityManager.merge(origUser);
        return origUser;
    }

    private void checkUser(String userId, String phone) {

        User user = userDao.readByPhone(phone);
        if (Objects.nonNull(user) && !user.getUserId().equals(userId)) {
            throw new AuthException(Result.E20001, "手机号已存在");
        }
    }

    public OAuthUser loginCheck(ApplicationOauthLoginReqDTO reqDTO) {
        User user = this.readByPhone(reqDTO.getPhone());
        if (Objects.isNull(user)){
            throw new AuthException("用户不存在");
        }
        if (!user.getPassword().equals(DigestUtils.md5Hex(user.getUserId() + reqDTO.getPassword()))){
            throw new AuthException("密码错误");
        }
        OAuthUser oAuthUser = CopyUtil.to(user, OAuthUser.class);
//        oAuthUser.setAuthorities(Lists.newArrayList("update"));
        oAuthUser.setMerchantCode(reqDTO.getMerchantCode());
        oAuthUser.setUsername(user.getUserName());
        return oAuthUser;
    }
}
